﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;
using Rhinestone.Shared;

namespace LinqRepositorySample.Tests
{
    public class IoCWindsorContainer : IoC
    {
         #region fields
        private WindsorContainer _container; //The actual container to use.
        #endregion

        #region methids
        public IoCWindsorContainer Configure()
        {
            Initialize(null);
            return this;
        }
        #endregion

        #region overrides
        /// Overriden. Initializes and configures the container to use the internal Windsor Container.
        /// </summary>
        /// <param name="configFilePath">string. An optional path to the external configuration file
        /// that should be used by the container to initialize itself.</param>
        protected override void Initialize(string configFilePath)
        {
            _container = string.IsNullOrEmpty(configFilePath) 
                            ? new WindsorContainer(new XmlInterpreter())
                            : new WindsorContainer(new XmlInterpreter(configFilePath));
        }

        /// <summary>
        /// Overriden, tries to resolve a component of the specified <typeparamref name="T"/> type and
        /// service name, retruning a new instance of the type if not found.
        /// </summary>
        /// <typeparam name="T">The type of component to resolve or build.</typeparam>
        /// <param name="serviceName">string. The component key that the component is registered with.</param>
        /// <returns>An instance of <typeparamref name="T"/>.</returns>
        /// <remarks>
        /// The <typeparamref name="T"/> must be a reference type that has a default new constructor. When
        /// implemented by a child class, implementors must return a new instance of the class if not found
        /// as a registered component.
        /// </remarks>
        public override T Resolve<T>(string serviceName)
        {
            return _container.Resolve<T>(serviceName);
        }

        /// <summary>
        /// Overriden, tries to resolve a component of the specified <paramref name="type"/>
        /// returning a new instance of the type <typeparam name="T"/>
        /// </summary>
        /// <param name="type">A <see cref="Type"/> instance representing the type to resolve.</param>
        /// <returns>object. The resolved component if it exists.</returns>
        public override T Resolve<T>(Type type)
        {
            return (T) _container.Resolve(type);
        }

        public override T Resolve<T>(Type type, string serviceName)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Overriden, tries to resolve a component of the specified <typeparamref name="T"/> type and
        /// retruning a new instance of the type if not found.
        /// </summary>
        /// <typeparam name="T">The type of component to resolve or build.</typeparam>
        /// <returns>An instance of <typeparamref name="T"/>.</returns>
        /// <remarks>
        /// The <typeparamref name="T"/> must be a reference type that has a default new constructor. When
        /// implemented by a child class, implementors must return a new instance of the class if not found
        /// as a registered component.
        /// </remarks>
        public override T Resolve<T>()
        {
            return _container.Resolve<T>();
        }

        /// <summary>
        /// Overriden, tries to resolve a component of the specified <typeparamref name="T"/> and
        /// service name type returning null (or default value for value types) when the component is not found.
        /// </summary>
        /// <typeparam name="T">The type of component to resolve.</typeparam>
        /// <param name="serviceName">string. The component key with which the component is registered.</param>
        /// <returns>An instance of <typeparamref name="T"/> type or null if the component is not found.</returns>
        public override T TryResolve<T>(string serviceName)
        {
            return TryResolve(serviceName, default(T));
        }

        /// <summary>
        /// Overriden, tries to resolve the component of the specified <typeparamref name="T"/> and
        /// service name type returning the default value when the component is not found.
        /// </summary>
        /// <typeparam name="T">The type of component to resolve.</typeparam>
        /// <param name="serviceName">string. The component key with which the compinent is registered.</param>
        /// <param name="defaultValue">The default value to return if not found.</param>
        /// <returns>An instance of <typeparamref name="T"/> instance.</returns>
        public override T TryResolve<T>(string serviceName, T defaultValue)
        {
            if (_container.Kernel.HasComponent(typeof(T)) &&
                _container.Kernel.HasComponent(serviceName))
                return _container.Resolve<T>(serviceName);
            return defaultValue;
        }

        /// <summary>
        /// Overriden, tries to resolve the component of the specified <typeparamref name="T"/> registered
        /// with the specified <paramref name="type"/> and service name. Returns the default value provided when
        /// the registered component is not found.
        /// </summary>
        /// <typeparam name="T">The type of component to resolve.</typeparam>
        /// <param name="type">The <see cref="Type"/> that the component is registered with.</param>
        /// <param name="serviceName">string. The component key with which the component is registered.</param>
        /// <param name="defaultValue">The default value to return in case the component is not registered.</param>
        /// <returns>An instance of <typeparamref name="T"/> type or the default value if the component is not found.</returns>
        public override T TryResolve<T>(Type type, string serviceName, T defaultValue)
        {

            if (_container.Kernel.HasComponent(type) &&
                _container.Kernel.HasComponent(serviceName))
                return (T) _container.Resolve(serviceName, type);
            return defaultValue;
        }

        /// <summary>
        /// Overriden, tries to resolve a component of the specified <typeparamref name="T"/> type and
        /// returns null (or default value for value types) when the component is not found.
        /// </summary>
        /// <typeparam name="T">The type of component to resolve.</typeparam>
        /// <returns>An instance of <typeparamref name="T"/> or null if the compnent is not found.</returns>
        public override T TryResolve<T>()
        {
            return TryResolve(default(T));
        }

        /// <summary>
        /// When overriden, tries to resolve a component of type <typeparam name="T"/> registered for the type
        /// <paramref name="type"/> and returns null (or default value for value types) when the component is not found.
        /// </summary>
        /// <param name="type">The registered component to resolve..</param>
        /// <returns>An instance of the component if found, else null.</returns>
        public override T TryResolve<T>(Type type)
        {
            return TryResolve(type, default(T));
        }

        /// <summary>
        /// Overriden, tries to resolve a component of the specified <typeparamref name="T"/> type and
        /// returns the default value provided when the component is not found.
        /// </summary>
        /// <typeparam name="T">The type of component to resolve.</typeparam>
        /// <param name="defaultValue">An optional default instance of <typeparamref name="T"/> that is
        /// returned in case the component could not be resolved.</param>
        /// <returns>An instance of <typeparamref name="T"/> type.</returns>
        public override T TryResolve<T>(T defaultValue)
        {
            if (_container.Kernel.HasComponent(typeof(T)))
                return _container.Resolve<T>();
            return defaultValue;
        }

        /// <summary>
        /// Overriden, tries to resolve a component of the specified <typeparam name="T"/> type registered
        /// with the <paramref name="type"/> and returns the default value provided when a component registeration
        /// is not provided.
        /// </summary>
        /// <param name="type">The <see cref="Type"/> that the component is registered with.</param>
        /// <param name="defaultValue">The default value to return in case the component is not registered.</param>
        /// <returns>An instance of <typeparamref name="T"/> type or the default value if the component is not found.</returns>
        public override T TryResolve<T>(Type type, T defaultValue)
        {
            if (_container.Kernel.HasComponent(type))
                return (T) _container.Resolve(type);
            return defaultValue;
        }
        #endregion
    }
}
